#include <bits/stdc++.h>
using namespace std;

struct Node {
  // 当前小爱坐标(x1,y1) 小艾坐标(x2,y2) 步数
  int x1, y1, x2, y2, step;
};
int n, m;
int dx[4] = {0, 0, -1, 1};
int dy[4] = {-1, 1, 0, 0};
char a[50][50];
bool vis[50][50][50][50];
// 是否越界，是否可以走
bool check(int x, int y) {
  return x >= 1 && x <= n && y >= 1 && y <= m && a[x][y] != '#';
}

queue<Node> Q;
Node st; // 初上状态

void bfs() {
  Q.push(st);
  vis[st.x1][st.y1][st.x2][st.y2] = 1;

  while (!Q.empty()) {
    Node f = Q.front();
    Q.pop();
    if (f.x1 == st.x2 && f.y1 == st.y2 && f.x2 == st.x1 && f.y2 == st.y1) {
      cout << f.step;
      return;
    }
    // 枚举小爱和小艾的所有方向组合
    for (int i = 0; i < 4; i++)
      for (int j = 0; j < 4; j++) {
        int nx1 = f.x1 + dx[i], ny1 = f.y1 + dy[i];
        int nx2 = f.x2 + dx[j], ny2 = f.y2 + dy[j];

        if (nx1 == f.x2 && ny1 == f.y2 && nx2 == f.x1 && ny2 == f.y1)
          continue;

        // 如果已经到终点, 原地保持不动
        if (f.x1 == st.x2 && f.y1 == st.y2)
          nx1 = f.x1, ny1 = f.y1;
        if (f.x2 == st.x1 && f.y2 == st.y1)
          nx2 = f.x2, ny2 = f.y2;

        if (check(nx1, ny1) && check(nx2, ny2)) {
          if (nx1 == nx2 && ny1 == ny2) { // 移动到同一个格子的情况
            if (!vis[nx1][ny1][f.x2][f.y2]) {
              vis[nx1][ny1][f.x2][f.y2] = 1;
              Q.push({nx1, ny1, f.x2, f.y2, f.step + 1});
            }
            if (!vis[f.x1][f.y1][nx2][ny2]) {
              vis[f.x1][f.y1][nx2][ny2] = 1;
              Q.push({f.x1, f.y1, nx2, ny2, f.step + 1});
            }
          } else { // 不是移动到同一个格子的情况
            if (!vis[nx1][ny1][nx2][ny2]) {
              vis[nx1][ny1][nx2][ny2] = 1;
              Q.push({nx1, ny1, nx2, ny2, f.step + 1});
            }
          }
        }
      }
  }
  cout << "No Solution";
}

int main() {
  cin >> n >> m;

  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++) {
      cin >> a[i][j];
      if (a[i][j] == '1')
        st.x1 = i, st.y1 = j;
      if (a[i][j] == '2')
        st.x2 = i, st.y2 = j;
    }
  bfs();
  return 0;
}
